home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 52
/
Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso
/
Aminet
/
gfx
/
misc
/
VLab_pss.lha
/
VLab_PSS
/
Sources
/
VLab.c
< prev
Wrap
C/C++ Source or Header
|
2002-10-27
|
46KB
|
1,330 lines
/*
** VLab plug-in for ArtEffect
** © 2002 Kakace Productions
**
*/
#define PLUGIN_VERSION "VLab.pss 1.8 (27.10.2002)"
#include <stdlib.h>
#ifndef INTUITION_INTUITION_H
#include <intuition/intuition.h>
#endif
#ifndef UTILITY_TAGITEM_H
#include <utility/tagitem.h>
#endif
#ifndef ARTEFFECT_AE_PLUGIN_H
#include <libraries/ae_plugin.h>
#endif
#ifndef MONITOR_H
#include "Monitor.h"
#endif
#ifndef VLAB_CONFIG_H
#include "VLab_Config.h"
#endif
#include <proto/exec.h>
#include <proto/ae_plugin.h>
#define COPYRIGHT PLUGIN_VERSION" © 2002, Kakace Productions.\0$VER: "PLUGIN_VERSION"\r\n"
/*------------------------------------------------------------------------------------------------*/
AE_DialogPtr PlugIn_OpenWindow(AE_AppObjPtr app);
void PlugIn_CloseWindow(AE_AppObjPtr app, AE_DialogPtr window);
void PlugIn_Apply(AE_AppObjPtr app, AE_EventPtr event);
struct VLabMonitor *PlugIn_HandleGadget(AE_AppObjPtr app, AE_DialogPtr window, AE_EventPtr event,
struct VLabMonitor *monitoring);
static void showError(AE_AppObjPtr app, ULONG errorID);
static void closeMonitor(struct VLabSettings *settings, struct VLabMonitor *monitor);
static void updateGadgets(AE_AppObjPtr app, AE_DialogPtr window, struct InputSettings *inputCfg);
/*
** Error codes and error strings for showError()
*/
enum PlugIn_ErrorID {
ERROR_NONE,
ERROR_NO_MEMORY,
ERROR_NO_WINDOW,
ERROR_VLAB_BUSY
};
static const char *PlugIn_Errors[] = {
"Not enough memory.",
"Unable to open the window.",
"The VLab is currently busy."
};
/*------------------------------------------------------------------------------------------------*/
/*
** Default settings
*/
static const struct VLabSettings DefSettings = {DEFAULT_CONF};
/*
** Global datas
*/
static struct VLabSettings SavedSettings; /* Loaded upon startup by ArtEffect */
static struct VLabSettings CurSettings; /* Current settings */
static ULONG MaxInputs; /* Max number of inputs. 2 = VLab Classic, 3 = VLab Y/C */
static UBYTE *RGB_Buffer; /* Allocated at startup time */
struct Library *AEPlugInBase;
/*
** Private functions
*/
static void handleEvents(AE_AppObjPtr application, AE_DialogPtr window);
static void set_monitoring_flags(struct VLabSettings *settings);
static struct VLabMonitor *open_monitor(AE_AppObjPtr app, AE_EventPtr event, struct VLabSettings *settings);
/*
** We cannot change all flags when the monitor is running.
** The mask below must be applied to filter flags changes in this case.
*/
#define MONITORING_MASK ~(VLABF_LACE | VLABF_HIRES)
/*------------------------------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
static struct TagItem tags[] = {
{PLUGIN_INFO_NAME, (ULONG) "VLab"},
{PLUGIN_INFO_COPYRIGHT, (ULONG) COPYRIGHT},
{PLUGIN_INFO_MENUTITLE, (ULONG) "VLab..."},
{PLUGIN_INFO_CONFIG, (ULONG) &SavedSettings},
{TAG_DONE}
};
int ret = EXIT_FAILURE;
if ( (AEPlugInBase = OpenLibrary("ArtEffect:libs/ae_plugin.library", 2)) ) {
struct TagItem *tagList; /* Initialization tag list */
AE_AppObjPtr app; /* Application object */
LONG plugInType; /* Plug-in type */
/*
** Initialize our plug-in
*/
SavedSettings = DefSettings;
plugInType = PLUGIN_TYPE_ERROR;
tagList = NULL;
if ( (MaxInputs = VLab_IdentifyHardware()) ) {
plugInType = PLUGIN_TYPE_SCANNER;
tagList = tags;
}
/*
** Event handling
*/
if ( (app = AE_SetupPlugInTagList(argc, argv, plugInType, tagList)) ) {
struct Task *task;
AE_DialogPtr window;
LONG oldPri;
enum PlugIn_ErrorID errcode = ERROR_NO_MEMORY;
task = FindTask(NULL);
oldPri = SetTaskPri(task, 0);
/*
** Allocate the YUV and RGB buffers now so that we won't have to deal with
** this if the user decide to digitize several picture before closing the
** window.
*/
if (VLab_AllocateYUV()) {
if ( (RGB_Buffer = (UBYTE *) AllocVec(VLAB_MAXWIDTH * VLAB_MAXHEIGHT_PAL * 3, MEMF_ANY)) ) {
errcode = ERROR_VLAB_BUSY;
if (VLab_OwnHardware()) {
errcode = ERROR_NO_WINDOW;
InitMonitoring(); /* Must be called before opening the main window */
CurSettings = SavedSettings;
if ( (window = PlugIn_OpenWindow(app)) ) {
handleEvents(app, window);
SavedSettings = CurSettings;
PlugIn_CloseWindow(app, window);
errcode = ERROR_NONE;
}
CleanupMonitoring();
VLab_FreeHardware();
}
FreeVec(RGB_Buffer);
}
VLab_FreeYUV();
}
showError(app, errcode);
AE_ExitPlugIn(app);
SetTaskPri(task, oldPri);
}
CloseLibrary(AEPlugInBase);
ret = EXIT_SUCCESS;
}
return ret;
}
static void handleEvents(AE_AppObjPtr app, AE_DialogPtr window)
{
struct VLabSettings *settings;
struct VLabMonitor *monitoring;
ULONG monitorBitMask = 0; /* Signal mask (monitoring) */
ULONG appBitMask; /* Signal mask (main window) */
int running = TRUE;
AE_EventPtr event;
settings = &CurSettings;
monitoring = NULL;
appBitMask = 1 << app->UserPort->mp_SigBit;
do {
int signals = 0;
/*
** If the monitoring is active, we poll the signals
** continuously. Otherwise, we wait for an event
** from ArtEffect.
*/
if (monitoring) {
UpdateMonitorWindow(monitoring);
monitorBitMask = 1 << MonitoringWindow(monitoring)->UserPort->mp_SigBit;
signals = SetSignal(0, 0);
}
else {
monitorBitMask = 0;
WaitPort(app->UserPort);
signals = appBitMask;
}
/*
** Handle monitoring window's IDCMP
*/
if (signals & monitorBitMask) {
struct IntuiMessage *imsg;
int close = FALSE;
SetSignal(0, signals & monitorBitMask);
while( (imsg = (struct IntuiMessage *) GetMsg(MonitoringWindow(monitoring)->UserPort)) ){
if (imsg->Class == IDCMP_CLOSEWINDOW)
close = TRUE;
ReplyMsg((struct Message *) imsg);
}
if (close) {
closeMonitor(settings, monitoring);
monitoring = NULL;
}
}
/*
** Handle plug-in window's messages.
*/
if (signals & appBitMask) {
SetSignal(0, signals & appBitMask);
while ( (event = AE_GetEvent(app)) ) {
switch (event->Type) {
case PLUGIN_EVENT_GADGET:
monitoring = PlugIn_HandleGadget(app, window, event, monitoring);
break;
case PLUGIN_EVENT_EXECUTE:
PlugIn_Apply(app, event);
/*
** Reset monitoring flags.
*/
if (monitoring)
set_monitoring_flags(settings);
break;
case PLUGIN_EVENT_QUIT:
running = FALSE;
if (monitoring) {
closeMonitor(settings, monitoring);
monitoring = NULL;
}
break;
}
AE_ReplyEvent(app, event);
}
}
} while (running);
}
static void closeMonitor(struct VLabSettings *settings, struct VLabMonitor *monitor)
{
settings->vs_WLeft = MonitoringWindow(monitor)->LeftEdge;
settings->vs_WTop = MonitoringWindow(monitor)->TopEdge;
CloseMonitorWindow(monitor);
}
static void showError(AE_AppObjPtr app, ULONG errorID)
{
if (errorID--) {
AE_DoRequestTags(app, AER_TYPE_INFO, AER_BodyText, (ULONG) PlugIn_Errors[errorID],
AER_TitleText, (ULONG) "VLab error", TAG_DONE);
}
}
/*------------------------------------------------------------------------------------------------*/
/****** VLab/PlugIn_OpenWindow **********************************************
*
* NAME
* PlugIn_OpenWindow -- Open the dialog window
*
* SYNOPSIS
* window = PlugIn_OpenWindow(app)
*
* AE_DialogPtr PlugIn_OpenWindow(AE_AppObjPtr);
*
* FUNCTION
* Open the dialog window. The window shall be closed by a call to the
* PlugIn_CloseWindow() function.
*
* INPUTS
* app - Object pointer returned by AE_SetupPlugInTagList().
*
* RESULT
* window - Pointer to the newly opened window, or NULL if an error occured
* or if no window is needed.
*
* NOTES
* Gadgets related to the monitoring feature might be disabled if the
* monitoring is not available (depending on the screen mode and the
* availability of the PiP feature).
*
* BUGS
*
* SEE ALSO
* PlugIn_CloseWindow(), AE_OpenWindowTagList()
*
*****************************************************************************
*
*/
/*
** Gadgets ID.
** Those ID depend upon the order in which each gadget appears in the tag list
** passed to AE_OpenWindowTags().
** We also use cycle gadgets instead of HRADIO because the latter are no longer
** supported by ArtEffect (all radio buttons are rendered verticaly).
*/
enum gadgetsID {
/* Video */
GADID_INPUT = 1, /* Input selector (cycle gadget). 2 or 3 values. */
GADID_VIDEO, /* Video mode (cycle gadget, 5 values) */
GADID_HUE, /* Hue value (integer) */
/* Filters */
GADID_VTR, /* VTR flag (checkbox) */
GADID_PREFILTER, /* Prefilter flag (checkbox) */
GADID_BW_SOURCE, /* B&W source flag (checkbox) */
GADID_BANDPASS, /* Bandpass filter (cycle gadget), 4 values */
GADID_CORING, /* Coring point (cycle gadget), 4 values */
GADID_WEIGHT, /* Filter weight (cycle gadget), 4 values */
/* Image */
GADID_HIRES, /* HiRes flag (checkbox) */
GADID_LACE, /* Lace flag (checkbox) */
GADID_COLOR, /* Greyscale flag (checkbox) */
GADID_GAMMA, /* Gamma correction (luma) */
GADID_BRIGHT, /* Brightness correction */
GADID_CONTRAST, /* Contrast correction */
/* Clipping */
GADID_XPOS, /* X position (integer) */
GADID_YPOS, /* Y position (integer) */
GADID_WIDTH, /* Width (integer) */
GADID_HEIGHT, /* Height (integer) */
/* Monitoring */
GADID_DISABLE_PIP, /* 1 = Disable PiP monitoring */
GADID_COLORMONITOR, /* 1 = Color monitoring */
GADID_RESOLUTION, /* Resolution ID (cycle gadget, 4 values) */
GADID_OPENMONITOR, /* Open monitor window (button) */
GADID_RESET, /* Reset configuration to last saved values */
};
AE_DialogPtr PlugIn_OpenWindow(AE_AppObjPtr app)
{
static const char *VLAB_YC_InputNames[] = {"Input", "CVBS-1", "CVBS-2", "S-VHS (Y/C)", NULL};
static const char *VLAB_InputNames[] = {"Input", "CVBS-1", "CVBS-2", NULL};
static const char *VLAB_Video[] = {"Source", "PAL B/G/H/I", "PAL N", "PAL M", "NTSC 4.43", "NTSC M", NULL};
static const char *VLAB_Resolutions[] = {"Preview", "Small", "Medium", "Large", NULL};
static const char *VLAB_Bandpass[] = {"Bandpass", "4.1 MHz", "3.8 MHz", "2.6 MHz", "2.9 MHz", NULL};
static const char *VLAB_Coring[] = {"Noise", "OFF", "Weak", "Medium", "Strong", NULL};
static const char *VLAB_Weight[] = {"K factor", "OFF", "Weak", "Medium", "Strong", NULL};
/*
** The GUI has to be modified depending upon the availability of the monitoring
** feature. The two tag lists below implement this.
*/
static const struct TagItem finalTags[] = {
{AE_Bar},
{AE_HGroup},
{PLUGIN_INFO_ID, GADID_RESET},
{PLUGIN_INFO_BUTTON, (ULONG) "Reset settings"}, /* GADGET */
{AE_Bar},
{PLUGIN_INFO_ACTION, (ULONG) "<< GRAB >>"}, /* GADGET */
{AE_EndGroup},
{PLUGIN_INFO_TITLE, (ULONG) "VLab settings..."},
{TAG_DONE}
};
static struct TagItem monitoringTags[] = { /* INDEX */
{AE_Title("Monitoring")}, /* 0 */
{AE_HGroup}, /* 1 */
{AE_VGroup}, /* 2 */
{PLUGIN_INFO_ACTIVE, 0}, /* 3 <== */
{PLUGIN_INFO_CHECKBOX, (ULONG) "Disable PiP"}, /* 4 GDGT */
{PLUGIN_INFO_ACTIVE, 0}, /* 5 <== */
{PLUGIN_INFO_CHECKBOX, (ULONG) "Color preview"}, /* 6 GDGT */
{AE_EndGroup}, /* 7 */
{AE_VGroup}, /* 8 */
{PLUGIN_INFO_ACTIVE, 1}, /* 9 <== */
{PLUGIN_INFO_CYCLE, (ULONG) VLAB_Resolutions}, /* GADGET */
{PLUGIN_INFO_BUTTON, (ULONG) "Start monitor"}, /* GADGET */
{AE_EndGroup},
{AE_EndGroup},
{TAG_MORE, (ULONG) finalTags}
};
struct VLabSettings *settings = &CurSettings;
struct InputSettings *inputCfg = &settings->vs_Settings[settings->vs_Input];
AE_DialogPtr window = NULL;
ULONG maxH, maxW, flags;
flags = inputCfg->is_Flags;
/*
** Verify the settings. ArtEffect automaticaly loads the settings from a
** configuration file, so we shall check the settings version and reload
** the default settings when a mismatch occurs.
*/
if (settings->vs_CfgVer != CONFIG_VERSION)
CurSettings = SavedSettings = DefSettings;
/*
** Setup default monitoring values in the related taglist.
*/
monitoringTags[3].ti_Data = (settings->vs_MonFlags & MONITOR_NO_PIP) ? 1 : 0;
monitoringTags[5].ti_Data = (settings->vs_MonFlags & MONITOR_COLOR) ? 1 : 0;
monitoringTags[9].ti_Data = settings->vs_Resolution;
/*
** Inform the vlab about the default settings.
*/
VLab_ChangeInput(settings->vs_Input);
VLab_ChangeVideo(inputCfg->is_VideoStd);
VLab_ChangeHue(inputCfg->is_Hue);
VLab_ChangeFlags(flags);
VLab_LumaCorrection(inputCfg->is_Gamma, inputCfg->is_Brightness, inputCfg->is_Contrast);
VLab_ChangeFilters(inputCfg->is_Filters);
maxH = VLab_FrameHeight(inputCfg->is_VideoStd, flags);
maxW = VLab_FrameWidth(flags);
/*
** Open the window.
** We use AE_OpenWindowTags() because most tags shall be initialized properly and
** because this allows us to modify the TagList without too much troubles.
**
** The default "Execute" button is replaced by an ACTION button. I don't know
** whether this is the right thing to do. Looks like it works though...
**
** ArtEffect forget the window title when the tag appear near the top of the
** tag list. I tried several things to figure out what happens, and I think it
** has something to do with Groups.
*/
if (!app->Quiet) {
window = AE_OpenWindowTags(app,
PLUGIN_INFO_ACTIVE, settings->vs_Input, /* GADGET */
PLUGIN_INFO_CYCLE, (ULONG) (MaxInputs == 2 ? VLAB_InputNames : VLAB_YC_InputNames),
PLUGIN_INFO_ACTIVE, inputCfg->is_VideoStd,
PLUGIN_INFO_CYCLE, (ULONG) VLAB_Video, /* GADGET */
PLUGIN_INFO_VALUE_MIN, -180,
PLUGIN_INFO_VALUE_MAX, 180,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Hue,
PLUGIN_INFO_VALUE, (ULONG) "Hue (NTSC)", /* GADGET */
AE_Title("Luminance filters"),
AE_HGroup,
AE_VGroup,
PLUGIN_INFO_ACTIVE, (flags & VLABF_VTR ? 1 : 0),
PLUGIN_INFO_CHECKBOX, (ULONG) "VTR", /* GADGET */
PLUGIN_INFO_ACTIVE, (flags & VLABF_PREFILTER ? 0 : 1),
PLUGIN_INFO_CHECKBOX, (ULONG) "Pre-filter", /* GADGET */
PLUGIN_INFO_ACTIVE, (flags & VLABF_BW_SOURCE ? 1 : 0),
PLUGIN_INFO_CHECKBOX, (ULONG) "B&W source", /* GADGET */
AE_EndGroup,
AE_VGroup,
PLUGIN_INFO_ACTIVE, FILTER_BANDPASS_R(inputCfg->is_Filters),
PLUGIN_INFO_CYCLE, (ULONG) VLAB_Bandpass, /* GADGET */
PLUGIN_INFO_ACTIVE, FILTER_CORING_R(inputCfg->is_Filters),
PLUGIN_INFO_CYCLE, (ULONG) VLAB_Coring, /* GADGET */
PLUGIN_INFO_ACTIVE, FILTER_FACTOR_R(inputCfg->is_Filters),
PLUGIN_INFO_CYCLE, (ULONG) VLAB_Weight, /* GADGET */
AE_EndGroup,
AE_EndGroup,
AE_Title("Image"),
AE_HGroup,
AE_VGroup,
PLUGIN_INFO_ACTIVE, (flags & VLABF_HIRES ? 1 : 0),
PLUGIN_INFO_CHECKBOX, (ULONG) "HiRes", /* GADGET */
PLUGIN_INFO_ACTIVE, (flags & VLABF_LACE ? 1 : 0),
PLUGIN_INFO_CHECKBOX, (ULONG) "Lace", /* GADGET */
PLUGIN_INFO_ACTIVE, (flags & VLABF_COLOR ? 1 : 0),
PLUGIN_INFO_CHECKBOX, (ULONG) "Color", /* GADGET */
AE_EndGroup,
AE_VGroup,
PLUGIN_INFO_VALUE_MIN, VLAB_GAMMA_MIN,
PLUGIN_INFO_VALUE_MAX, VLAB_GAMMA_MAX,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Gamma,
PLUGIN_INFO_VALUE, (ULONG) "Gamma", /* GADGET */
PLUGIN_INFO_VALUE_MIN, VLAB_BRIGHT_MIN,
PLUGIN_INFO_VALUE_MAX, VLAB_BRIGHT_MAX,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Brightness,
PLUGIN_INFO_VALUE, (ULONG) "Brightness", /* GADGET */
PLUGIN_INFO_VALUE_MIN, VLAB_CONTRAST_MIN,
PLUGIN_INFO_VALUE_MAX, VLAB_CONTRAST_MAX,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Contrast,
PLUGIN_INFO_VALUE, (ULONG) "Contrast", /* GADGET */
AE_EndGroup,
AE_EndGroup,
AE_Title("Clipping"),
PLUGIN_INFO_VALUE_MIN, 0,
PLUGIN_INFO_VALUE_MAX, maxW - inputCfg->is_Width,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_XPos,
PLUGIN_INFO_VALUE, (ULONG) "X pos", /* GADGET */
PLUGIN_INFO_VALUE_MIN, 0,
PLUGIN_INFO_VALUE_MAX, maxH - inputCfg->is_Height,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_YPos,
PLUGIN_INFO_VALUE, (ULONG) "Y pos", /* GADGET */
PLUGIN_INFO_VALUE_MIN, 4,
PLUGIN_INFO_VALUE_MAX, maxW - inputCfg->is_XPos,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Width,
PLUGIN_INFO_VALUE, (ULONG) "Width", /* GADGET */
PLUGIN_INFO_VALUE_MIN, 2,
PLUGIN_INFO_VALUE_MAX, maxH - inputCfg->is_YPos,
PLUGIN_INFO_VALUE_DEF, inputCfg->is_Height,
PLUGIN_INFO_VALUE, (ULONG) "Height", /* GADGET */
TAG_MORE, (ULONG) (IsMonitoringAvailable(app->PubScreenName) ? monitoringTags : finalTags));
}
return window;
}
/****** VLab/PlugIn_CloseWindow *********************************************
*
* NAME
* PlugIn_CloseWindow -- Close the dialog window.
*
* SYNOPSIS
* PlugIn_CloseWindow(app, window)
*
* void PlugIn_CloseWindow(AE_AppObjPtr, AE_DialogPtr);
*
* FUNCTION
* Close the dialog window opened by PlugIn_OpenWindow().
*
* INPUTS
* app - Application object obtained by AE_SetupPlugInTagList().
* window - Window pointer obtained by PlugIn_OpenWindow(). It's safe to
* pass a NULL pointer.
*
* SEE ALSO
* PlugIn_OpenWindow(), AE_CloseWindow()
*
*****************************************************************************
*
*/
void PlugIn_CloseWindow(AE_AppObjPtr app, AE_DialogPtr window)
{
if (window)
AE_CloseWindow(app, window);
}
/****** VLab/PlugIn_HandleGadget ********************************************
*
* NAME
* PlugIn_HandleGadget -- Handle a gadget event.
*
* SYNOPSIS
* monitoring = PlugIn_HandleGadget(app, window, event, monitoring)
*
* struct VLabMonitor *PlugIn_HandleGadget(AE_AppObjPtr, AE_DialogPtr,
* AE_EventPtr, struct VLabMonitor *);
*
* FUNCTION
* Handle a gadget event.
*
* INPUTS
* app - Application object obtained by AE_SetupPlugInTagList().
* window - Window pointer obtained by PlugIn_OpenWindow().
* event - Event pointer :
* event->ID : Gadget ID.
* event->Value : New gadget value.
*
* RESULT
* monitoring - Pointer to a monitoring object.
* event->Error : Optional error code.
*
* NOTES
* The HiRes and Lace flags are not sent to the vlab hardware, but the
* settings always reflect any changes made by the user. This means that
* the full set of flags must be sent to the hardware before grabbing a
* new picture.
* The "B&W source" gadget, when set, force any grab (as well as the
* monitoring) in greyscale mode.
*
* SEE ALSO
*
*****************************************************************************
*
* The "hires" and "lace" flags must not be sent to the vlab to avoid
* conflicts with the monitoring feature.
* Therefore, all flags sent to the VLab hardware by a call to the
* VLab_ChangeFlags function must be masked by MONITORING_MASK to avoid
* side effects. This allows the user to see the effect of the other flags
* while monitoring the current input.
*/
struct VLabMonitor *PlugIn_HandleGadget(AE_AppObjPtr app, AE_DialogPtr window,
AE_EventPtr event, struct VLabMonitor *monitoring)
{
ULONG height, width, xScale, yScale;
struct VLabSettings *settings = &CurSettings;
struct InputSettings *inputCfg = &settings->vs_Settings[settings->vs_Input];
LONG value = event->Value;
ULONG flags = inputCfg->is_Flags;
height = VLab_FrameHeight(inputCfg->is_VideoStd, flags);
width = VLab_FrameWidth(flags);
xScale = (flags & VLABF_HIRES) ? 4 : 2;
yScale = (flags & VLABF_LACE) ? 2 : 1;
/*
** Handle all gadgets.
** When a value concerning the image's dimensions is changed, the code takes care
** to modify other related settings (xpos<->width and ypos<->height)
** When the monitoring is active, some values need to be changed in real time so
** that their effect applies to the monitoring as well.
*/
switch(event->ID) {
/*
** ########## Video ##########
*/
case GADID_INPUT: /* Input : CVBS1 / CVBS2 / SVHS */
settings->vs_Input = value; /* Value : [0; 2] */
inputCfg = &settings->vs_Settings[value];
updateGadgets(app, window, inputCfg);
VLab_ChangeInput(value);
break;
case GADID_VIDEO: /* PAL B/G/H/I, N, M, NTSC 4.43, M */
inputCfg->is_VideoStd = value;
VLab_ChangeVideo(value);
height = VLab_FrameHeight(value, flags);
/*
** Update YPos/Height gadgets.
** When switching from PAL to NTSC, the current frame size
** is scaled down to fit into the new limits.
*/
if (inputCfg->is_Height + inputCfg->is_YPos > height) {
inputCfg->is_Height = (inputCfg->is_Height * 5) / 6;
inputCfg->is_YPos = (inputCfg->is_YPos * 5) / 6;
if (flags & VLABF_LACE) {
inputCfg->is_Height &= ~1;
inputCfg->is_YPos &= ~1;
}
}
AE_SetSlider(app, window, GADID_YPOS, inputCfg->is_YPos, 0, height - inputCfg->is_Height);
AE_SetSlider(app, window, GADID_HEIGHT, inputCfg->is_Height, yScale, height - inputCfg->is_YPos);
/*
** Resize the monitoring window. If this fails, the monitoring
** is no longer active.
*/
if (monitoring) {
value = settings->vs_Resolution;
if (inputCfg->is_VideoStd >= VIDEO_525)
value += MONITOR_SIZES;
monitoring = ResizeMonitor(monitoring, app->PubScreenName, value);
}
break;
case GADID_HUE: /* Hue (NTSC only) */
inputCfg->is_Hue = value;
VLab_ChangeHue(value);
break;
/*
** ########## Filters ##########
*/
case GADID_VTR: /* Video Tape Recorder flag */
flags &= ~VLABF_VTR;
if (value)
flags |= VLABF_VTR;
inputCfg->is_Flags = flags;
VLab_ChangeFlags(flags & MONITORING_MASK);
break;
case GADID_PREFILTER: /* Not checked : disabled */
flags &= ~VLABF_PREFILTER;
if (!value)
flags |= VLABF_PREFILTER;
inputCfg->is_Flags = flags;
VLab_ChangeFlags(flags & MONITORING_MASK);
break;
case GADID_BW_SOURCE: /* Disable chroma filter */
flags &= ~VLABF_BW_SOURCE;
if (value)
flags |= VLABF_BW_SOURCE;
inputCfg->is_Flags = flags;
VLab_ChangeFlags(flags & MONITORING_MASK);
if (monitoring)
MonitorChangeMode(monitoring, ((settings->vs_MonFlags & MONITOR_COLOR) && !value ? TRUE : FALSE));
break;
case GADID_BANDPASS:
inputCfg->is_Filters = FILTER_BANDPASS_W(inputCfg->is_Filters, value);
VLab_ChangeFilters(inputCfg->is_Filters);
break;
case GADID_CORING:
inputCfg->is_Filters = FILTER_CORING_W(inputCfg->is_Filters, value);
VLab_ChangeFilters(inputCfg->is_Filters);
break;
case GADID_WEIGHT:
inputCfg->is_Filters = FILTER_FACTOR_W(inputCfg->is_Filters, value);
VLab_ChangeFilters(inputCfg->is_Filters);
break;
/*
** ########## Image ##########
*/
case GADID_GAMMA: /* Gamma correction */
inputCfg->is_Gamma = value;
VLab_LumaCorrection(inputCfg->is_Gamma, inputCfg->is_Brightness, inputCfg->is_Contrast);
break;
case GADID_BRIGHT: /* Brightness */
inputCfg->is_Brightness = value;
VLab_LumaCorrection(inputCfg->is_Gamma, inputCfg->is_Brightness, inputCfg->is_Contrast);
break;
case GADID_CONTRAST: /* Contrast */
inputCfg->is_Contrast = value;
VLab_LumaCorrection(inputCfg->is_Gamma, inputCfg->is_Brightness, inputCfg->is_Contrast);
break;
case GADID_LACE: /* Lace / No lace */
flags &= ~VLABF_LACE;
yScale = 1;
if (value) {
flags |= VLABF_LACE;
yScale = 2;
}
inputCfg->is_Flags = flags;
height = VLab_FrameHeight(inputCfg->is_VideoStd, flags);
/*
** Update YPos/Height gadgets.
** Both YPos/Height are scaled when they overflow the current
** frame height or when the user switches to interlaced mode.
** Otherwise, only the limits are changed.
*/
if (value) {
inputCfg->is_YPos *= 2;
inputCfg->is_Height *= 2;
}
else {
if (inputCfg->is_YPos + inputCfg->is_Height > height) {
inputCfg->is_YPos = inputCfg->is_YPos / 2;
inputCfg->is_Height = inputCfg->is_Height / 2;
}
}
AE_SetSlider(app, window, GADID_YPOS, inputCfg->is_YPos, 0, height - inputCfg->is_Height);
AE_SetSlider(app, window, GADID_HEIGHT, inputCfg->is_Height, yScale, height - inputCfg->is_YPos);
/* AE bug ? In some case, the gadget value is not updated properly. */
/* This is the case when the new value exceeds the current limit. */
AE_SetGadget(app, window, GADID_YPOS, inputCfg->is_YPos);
AE_SetGadget(app, window, GADID_HEIGHT, inputCfg->is_Height);
break;
case GADID_HIRES:
flags &= ~VLABF_HIRES;
xScale = 1;
if (value) {
flags |= VLABF_HIRES;
xScale = 2;
}
inputCfg->is_Flags = flags;
width = VLab_FrameWidth(flags);
/*
** Update XPos/Width gadgets.
** Both XPos/Width are scaled when they overflow the current
** frame width or when the user switches to HiRes mode.
** Otherwise, only the limits are changed.
*/
if (value) {
inputCfg->is_XPos *= 2;
inputCfg->is_Width *= 2;
}
else {
if (inputCfg->is_XPos + inputCfg->is_Width > width) {
inputCfg->is_XPos = (inputCfg->is_XPos / 2) & ~1;
inputCfg->is_Width = (inputCfg->is_Width / 2) & ~1;
}
}
AE_SetSlider(app, window, GADID_XPOS, inputCfg->is_XPos, 0, width - inputCfg->is_Width);
AE_SetSlider(app, window, GADID_WIDTH, inputCfg->is_Width, xScale, width - inputCfg->is_XPos);
/* AE bug ? In some case, the gadget value is not updated properly. */
/* This is the case when the new value exceeds the current limit. */
AE_SetGadget(app, window, GADID_XPOS, inputCfg->is_XPos);
AE_SetGadget(app, window, GADID_WIDTH, inputCfg->is_Width);
break;
case GADID_COLOR:
flags &= ~VLABF_COLOR;
if (value)
flags |= VLABF_COLOR;
inputCfg->is_Flags = flags;
break;
/*
** ########## Clipping ##########
**
**
** The following values shall be rounded properly.
** X, Width : granule = 4 (HiRes) or 2 (LoRes)
** Y, Height : granule = 1 (single frame) or 2 (interlaced mode)
** Each time the user changes one setting, the maximum limit of
** this setting's counter-part is modified (xpos<->width and
** ypos<->height)
*/
case GADID_XPOS:
if (value > inputCfg->is_XPos)
value += xScale - 1;
value &= -xScale;
inputCfg->is_XPos = value;
AE_SetGadget(app, window, GADID_XPOS, value);
AE_SetSlider(app, window, GADID_WIDTH, inputCfg->is_Width, xScale, width - value);
break;
case GADID_YPOS:
if (value > inputCfg->is_YPos)
value++;
if (flags & VLABF_LACE)
value &= -yScale;
inputCfg->is_YPos = value;
AE_SetGadget(app, window, GADID_YPOS, value);
AE_SetSlider(app, window, GADID_HEIGHT, inputCfg->is_Height, yScale, height - value);
break;
case GADID_WIDTH:
if (value > inputCfg->is_Width)
value += xScale - 1;
value &= -xScale;
inputCfg->is_Width = value;
AE_SetGadget(app, window, GADID_WIDTH, value);
AE_SetSlider(app, window, GADID_XPOS, inputCfg->is_XPos, 0, width - value);
break;
case GADID_HEIGHT:
if (value > inputCfg->is_Height)
value++;
if (flags & VLABF_LACE)
value &= -yScale;
inputCfg->is_Height = value;
AE_SetGadget(app, window, GADID_HEIGHT, value);
AE_SetSlider(app, window, GADID_YPOS, inputCfg->is_YPos, 0, height - value);
break;
/*
** ########## Monitoring ##########
*/
case GADID_COLORMONITOR:
flags = settings->vs_MonFlags & ~MONITOR_COLOR;
if (value)
flags |= MONITOR_COLOR;
settings->vs_MonFlags = flags;
set_monitoring_flags(settings);
if (monitoring && !(inputCfg->is_Flags & VLABF_BW_SOURCE))
MonitorChangeMode(monitoring, value);
break;
case GADID_DISABLE_PIP:
flags = settings->vs_MonFlags & ~MONITOR_NO_PIP;
if (value)
flags |= MONITOR_NO_PIP;
settings->vs_MonFlags = flags;
if (monitoring) {
CloseMonitorWindow(monitoring);
monitoring = open_monitor(app, event, settings);
}
break;
case GADID_RESOLUTION:
settings->vs_Resolution = value;
if (inputCfg->is_VideoStd >= VIDEO_525)
value += MONITOR_SIZES;
/*
** Resize the monitoring window. If this fails, the monitoring
** is no longer active.
*/
if (monitoring)
monitoring = ResizeMonitor(monitoring, app->PubScreenName, value);
break;
case GADID_OPENMONITOR:
if (!monitoring)
monitoring = open_monitor(app, event, settings);
break;
/*
** ########## RESET ##########
*/
case GADID_RESET:
/*
** Reset input specific settings to their last saved values.
*/
settings->vs_Settings[settings->vs_Input] = SavedSettings.vs_Settings[settings->vs_Input];
updateGadgets(app, window, inputCfg);
/*
** Update vlab's internal state.
*/
VLab_ChangeFilters(inputCfg->is_Filters);
VLab_ChangeHue(inputCfg->is_Hue);
VLab_ChangeFlags(inputCfg->is_Flags & MONITORING_MASK);
VLab_ChangeVideo(value);
VLab_LumaCorrection(inputCfg->is_Gamma, inputCfg->is_Brightness, inputCfg->is_Contrast);
if (monitoring) {
MonitorChangeMode(monitoring, ((settings->vs_MonFlags & MONITOR_COLOR) &&
!(inputCfg->is_Flags & VLABF_BW_SOURCE) ? TRUE : FALSE));
}
break;
}
return monitoring;
}
/****i* VLab/updateGadgets **************************************************
*
* NAME
* updateGadgets -- Update gadgets related to input specific settings.
*
* SYNOPSIS
* updateGadgets(app, window, inputCfg)
*
* static void updateGadgets(AE_AppObjPtr, AE_DialogPtr, struct InputSettings *);
*
* FUNCTION
* Update the gadgets that reflect input specific settings (image size and
* dimension, filters, video mode, etc).
*
* INPUTS
* app - Application object obtained by AE_SetupPlugInTagList().
* window - Window pointer obtained by PlugIn_OpenWindow().
* inputCfg - Input specific settings.
*
* SEE ALSO
*
*****************************************************************************
*
*/
static void updateGadgets(AE_AppObjPtr app, AE_DialogPtr window, struct InputSettings *inputCfg)
{
ULONG xScale, yScale, max_width, max_height;
ULONG flags = inputCfg->is_Flags;
AE_SetGadget(app, window, GADID_BANDPASS, FILTER_BANDPASS_R(inputCfg->is_Filters));
AE_SetGadget(app, window, GADID_CORING, FILTER_CORING_R(inputCfg->is_Filters));
AE_SetGadget(app, window, GADID_WEIGHT, FILTER_FACTOR_R(inputCfg->is_Filters));
AE_SetGadget(app, window, GADID_VTR, ((flags & VLABF_VTR) ? 1 : 0));
AE_SetGadget(app, window, GADID_PREFILTER, ((flags & VLABF_PREFILTER) ? 0 : 1));
AE_SetGadget(app, window, GADID_BW_SOURCE, ((flags & VLABF_BW_SOURCE) ? 1 : 0));
AE_SetGadget(app, window, GADID_HIRES, ((flags & VLABF_HIRES) ? 1 : 0));
AE_SetGadget(app, window, GADID_LACE, ((flags & VLABF_LACE) ? 1 : 0));
AE_SetGadget(app, window, GADID_COLOR, ((flags & VLABF_COLOR) ? 1 : 0));
AE_SetGadget(app, window, GADID_GAMMA, inputCfg->is_Gamma);
AE_SetGadget(app, window, GADID_BRIGHT, inputCfg->is_Brightness);
AE_SetGadget(app, window, GADID_CONTRAST, inputCfg->is_Contrast);
AE_SetGadget(app, window, GADID_HUE, inputCfg->is_Hue);
AE_SetGadget(app, window, GADID_VIDEO, inputCfg->is_VideoStd);
/*
** Update image dimension/position gadgets.
*/
max_height = VLab_FrameHeight(inputCfg->is_VideoStd, flags);
max_width = VLab_FrameWidth(flags);
xScale = (flags & VLABF_HIRES) ? 4 : 2;
yScale = (flags & VLABF_LACE) ? 2 : 1;
AE_SetSlider(app, window, GADID_XPOS, inputCfg->is_XPos, 0, max_width - inputCfg->is_Width);
AE_SetSlider(app, window, GADID_WIDTH, inputCfg->is_Width, xScale, max_width - inputCfg->is_XPos);
AE_SetSlider(app, window, GADID_YPOS, inputCfg->is_YPos, 0, max_height - inputCfg->is_Height);
AE_SetSlider(app, window, GADID_HEIGHT, inputCfg->is_Height, yScale, max_height - inputCfg->is_YPos);
/* AE bug ? In some case, the gadget value is not updated properly. */
/* This is the case when the new value exceeds the current limit. */
AE_SetGadget(app, window, GADID_XPOS, inputCfg->is_XPos);
AE_SetGadget(app, window, GADID_WIDTH, inputCfg->is_Width);
AE_SetGadget(app, window, GADID_YPOS, inputCfg->is_YPos);
AE_SetGadget(app, window, GADID_HEIGHT, inputCfg->is_Height);
}
/****** VLab/PlugIn_Apply ***************************************************
*
* NAME
* PlugIn_Apply -- Apply the plug-in's effect
*
* SYNOPSIS
* PlugIn_Apply(app, event)
*
* void PlugIn_Apply(AE_AppObjPtr, AE_EventPtr);
*
* FUNCTION
* Digitize a picture based on the current settings. A new paint window is
* opened only if the operation succeeds.
*
* INPUTS
* app - Application object obtained by AE_SetupPlugInTagList().
* event - Event pointer. event->Object points to the object the effect
* shall be applied to.
*
* RESULT
* event->Error : Optional error code.
*
* SEE ALSO
*
*****************************************************************************
*
* The YUV buffer required by VLab_Grab() has been allocated when we opened
* the window. Thus, the pointer remains valid even if the user digitizes
* several pictures without closing the window.
*
* The function reset all "flags" settings before processing. Some of those
* flags cannot be changed when the user modify them because this collides
* with the monitoring feature.
*/
void PlugIn_Apply(AE_AppObjPtr app, AE_EventPtr event)
{
struct InputSettings *inputCfg = &CurSettings.vs_Settings[CurSettings.vs_Input];
long errCode = PLUGIN_ERROR_MEMORY; /* Default : No memory error */
AE_ObjPtr Picture; /* Current Picture object to grab to. */
/*
** Allocate a new picture object (we'll display the new image there)
** then create an access cache for this object.
*/
if ( (Picture = AE_AllocPicture(app, inputCfg->is_Width, inputCfg->is_Height,
((inputCfg->is_Flags & VLABF_COLOR) ? PIC_RGB : PIC_GRAYSCALE))) ) {
int vlabErr, colorFlag;
ULONG mode, line;
/*
** The monitoring activity uses different settings. Make sure we use
** the right ones for the final shot.
*/
VLab_ChangeFlags(inputCfg->is_Flags);
mode = (inputCfg->is_Flags & VLABF_HIRES) ? CAPTURE_HIRES : CAPTURE_LORES;
colorFlag = ((inputCfg->is_Flags & (VLABF_COLOR | VLABF_BW_SOURCE)) == VLABF_COLOR);
AE_BeginOperation(app, Picture, "Digitizing...");
if (VLab_InitHardware())
vlabErr = VLABERR_I2C;
else
vlabErr = VLab_Grab(inputCfg->is_XPos, inputCfg->is_YPos, inputCfg->is_Width, inputCfg->is_Height,
mode, colorFlag);
/*
** Fill-in the picture object. In greyscale mode, the Luma component is
** used as is.
*/
if (vlabErr == VLABERR_OK) {
UBYTE *buffer;
ULONG step;
ULONG colorMode;
if (colorFlag) {
buffer = RGB_Buffer;
step = inputCfg->is_Width * 3;
colorMode = BITMAP_TYPE_RGB;
VLab_YUV_to_RGB(buffer, inputCfg->is_Width * inputCfg->is_Height,
((inputCfg->is_Flags & VLABF_HIRES) ? CAPTURE_HIRES : CAPTURE_LORES));
}
else {
buffer = VLab_GetYBuffer();
step = inputCfg->is_Width;
colorMode = BITMAP_TYPE_GRAY8;
}
/*
** ArtEffect bitmap is filled line by line (there's no way to copy
** the image in one go).
*/
for (line = 0; line < inputCfg->is_Height; line++, buffer += step)
AE_WriteHLine(app, Picture, buffer, 0, line, inputCfg->is_Width, colorMode);
}
AE_EndOperation(app, Picture);
if (vlabErr == VLABERR_OK) {
AE_SetPicture(app, Picture);
errCode = PLUGIN_ERROR_NONE;
}
else {
const char *text;
AE_FreePicture(app, Picture);
errCode = PLUGIN_ERROR_CUSTOM;
text = VLab_GetErrorString(vlabErr);
AE_DoRequestTags(app, AER_TYPE_INFO, AER_BodyText, (ULONG) text, AER_TitleText, (ULONG) "VLab error", TAG_DONE);
}
}
event->Error = errCode;
}
/****i* VLab/set_monitoring_flags *******************************************
*
* NAME
* set_monitoring_flags -- Set monitoring specific flags
*
* SYNOPSIS
* set_monitoring_flags(settings)
*
* void set_monitoring_flags(struct VLabSettings *);
*
* FUNCTION
* Initialize the VLab hardware for LoRes non-lace scanning.
*
* INPUTS
* settings - Pointer to the actual settings.
*
* SEE ALSO
*
*****************************************************************************
*
*/
static void set_monitoring_flags(struct VLabSettings *settings)
{
ULONG flags = settings->vs_Settings[settings->vs_Input].is_Flags & MONITORING_MASK;
VLab_ChangeFlags(flags);
}
/****i* VLab/open_monitor ***************************************************
*
* NAME
* open_monitor -- Open the monitoring window
*
* SYNOPSIS
* monitorHandle = open_monitor(app, event, settings)
*
* struct VLabMonitor *open_monitor(AE_AppObjPtr, AE_EventPtr,
* struct VLabSettings *);
*
* FUNCTION
* Open the monitoring window, which is either a standard window or a PiP
* layer.
*
* INPUTS
* app - Application object pointer.
* event - Event pointer.
* settings - Pointer to the current settings.
*
* RESULT
* monitorHandle - Pointer to a private Monitor structure, or NULL if the
* monitoring is not available for some reason. If the monitoring
* fails, the function displays an error requester and set the
* event's error code to PLUGIN_ERROR_CUSTOM.
*
* SEE ALSO
*
*****************************************************************************
*
*/
static struct VLabMonitor *open_monitor(AE_AppObjPtr app, AE_EventPtr event, struct VLabSettings *settings)
{
struct VLabMonitor *monitor;
ULONG resolution = settings->vs_Resolution;
ULONG monFlags = settings->vs_MonFlags;
if (settings->vs_Settings[settings->vs_Input].is_VideoStd >= VIDEO_525)
resolution += MONITOR_SIZES;
/*
** Setup monitoring settings.
*/
if (settings->vs_Settings[settings->vs_Input].is_Flags & VLABF_BW_SOURCE)
monFlags &= ~MONITOR_COLOR;
if ( (monitor = OpenMonitorWindow(app->PubScreenName, settings->vs_WLeft, settings->vs_WTop,
resolution, monFlags)) ) {
set_monitoring_flags(settings);
}
else if (event) {
event->Error = PLUGIN_ERROR_CUSTOM;
AE_DoRequestTags(app, AER_TYPE_INFO, AER_BodyText, (ULONG) "Monitoring not available.", (ULONG) "GUI error", TAG_DONE);
}
return monitor;
}